package cn.zebra.dev.member.module.client.controller;

import cn.zebra.dev.common.constant.SysConstant;
import cn.zebra.dev.common.restful.Result;
import cn.zebra.dev.common.utils.NumberUtils;
import cn.zebra.dev.common.utils.SecurityUtils;
import cn.zebra.dev.common.utils.StrUtils;
import cn.zebra.dev.feign.service.SmsService;
import cn.zebra.dev.member.module.client.vo.ForgetPasswordVO;
import cn.zebra.dev.member.module.client.vo.LoginVO;
import cn.zebra.dev.member.module.client.vo.RegisterVO;
import cn.zebra.dev.member.module.login.service.LoginService;
import cn.zebra.dev.member.module.login.service.SecurityMemberService;
import cn.zebra.dev.member.module.member.entity.MemberEntity;
import cn.zebra.dev.member.module.member.service.MemberService;
import cn.zebra.dev.utils.module.kaptcha.ImageUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import cn.zebra.dev.common.utils.StrUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.security.auth.Subject;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;

/**
 * @author runnable@sina.cn
 */
@Api(tags = "用户登录注册")
@RestController
public class ClientController {

    @Autowired
    private LoginService loginService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private SecurityMemberService securityMemberService;

    @Autowired
    private MemberService memberService;

    @Autowired
    private SmsService smsService;

    @GetMapping("/forgetPasswordPhone/{phone}")
    @ApiOperation("忘记密码 - 获取手机验证码")
    public Result forgetPasswordPhone(@PathVariable String phone) {
        MemberEntity entity = memberService.findMemberByPhone(phone);
        if (entity == null) {
            return Result.error("该手机号暂未注册用户！");
        }
        String key = SysConstant.FORGET_PASSWORD_CODE + phone;
        Integer code = NumberUtils.getRandom(100000, 999999);
        Integer minute = 3;
        Map<String, Object> sendMap = new HashMap<>(5);
        sendMap.put("key", key);
        sendMap.put("phone", phone);
        sendMap.put("content", String.format("【%s】您的注册验证码是：%s。%s分钟内有效，请勿告诉他人。", "TMT", code, minute));
        sendMap.put("code", code);
        sendMap.put("minute", minute);
        return smsService.sendContent(sendMap);
    }

    @GetMapping("/registerCodePhone/{phone}")
    @ApiOperation("注册 - 获取手机验证码")
    public Result registerCode(@PathVariable String phone) {
        MemberEntity member = memberService.findMemberByPhone(phone);
        if (member != null) {
            return Result.error("该手机号已注册！");
        }
        String key = SysConstant.PHONE_REG_CODE_PREFIX + phone;
        Integer code = NumberUtils.getRandom(100000, 999999);
        Integer minute = 3;
        Map<String, Object> sendMap = new HashMap<>(5);
        sendMap.put("key", key);
        sendMap.put("phone", phone);
        sendMap.put("content", String.format("【%s】您的注册验证码是：%s。%s分钟内有效，请勿告诉他人。", "TMT", code, minute));
        sendMap.put("code", code);
        sendMap.put("minute", minute);
        return smsService.sendContent(sendMap);
    }

    @PostMapping("register")
    @ApiOperation("注册")
    @Transactional(rollbackFor = Exception.class)
    public Result register(@Valid @RequestBody RegisterVO registerVO) {
        String key = SysConstant.PHONE_REG_CODE_PREFIX + registerVO.getPhone();
        ValueOperations<String, String> operations = redisTemplate.opsForValue();
        String code = operations.get(key);
        if (StrUtils.isBlank(code)) {
            return Result.error("您的验证码已过期!请重新发送");
        }
        if (!registerVO.getCode().equals(code.replace("\"", ""))) {
            return Result.error("验证码不正确!");
        }
        MemberEntity memberEntity = new MemberEntity();
        String memberCode;
        do {
            memberCode = ImageUtils.generationCode(6);
        } while (memberService.findByMemberCode(memberCode) != null);
        memberEntity.setMemberCode(memberCode);
        memberEntity.setPhone(registerVO.getPhone());
        //盐
        String salt = SecurityUtils.getMd5(StrUtils.getUUID());
        //生成密码
        memberEntity.setSalt(salt);
        memberEntity.setPassword(SecurityUtils.getMd5(salt + registerVO.getPassword()));
        memberEntity.setMemberPath("");
        memberEntity.setSecondarySalt("");
        memberEntity.setSecondaryPassword("");
        memberService.saveMember(memberEntity);

        Long memberId = memberEntity.getId();

        memberCode = registerVO.getMemberCode();
        if (StrUtils.isNotBlank(memberCode)) {
            MemberEntity parentMember = memberService.findByMemberCode(memberCode);
            if (parentMember == null) {
                throw new RuntimeException("邀请人不存在!");
            }
            memberEntity.setParentId(parentMember.getId());
            memberEntity.setMemberPath(parentMember.getMemberPath() + String.format("%s^", memberId));
        } else {
            memberEntity.setMemberPath("^" + memberId + "^");
        }
        if (!memberService.updateById(memberEntity)) {
            throw new RuntimeException("注册失败！");
        }

        operations.getOperations().delete(key);
        return Result.success("注册成功！");
    }

    @PostMapping("/forgetPassword")
    @ApiOperation("忘记密码 - 修改密码")
    public Result forgetPassword(@Valid @RequestBody ForgetPasswordVO param) {
        String phone = param.getPhone();
        String key = SysConstant.FORGET_PASSWORD_CODE + phone;
        ValueOperations<String, String> operations = redisTemplate.opsForValue();
        String code = operations.get(key);
        if (StrUtils.isBlank(code)) {
            return Result.error("修改失败！请返回上一步重新获取验证码！");
        }
        if (!param.getCode().equals(code.replace("\"", ""))) {
            return Result.error("验证码不正确!");
        }
        operations.getOperations().delete(key);
        //效验验证码
        String password = param.getPassword();
        MemberEntity member = memberService.findMemberByPhone(phone);
        if (member == null) {
            return Result.error("您还未用手机注册!");
        }
        String salt = member.getSalt();
        password = SecurityUtils.getMd5(salt + password);
        if (member.getPassword().equals(password)) {
            return Result.error("您现在的登录密码和新密码一致!");
        }
        if (memberService.updateMemberPassword(phone, password)) {
            return Result.success("修改成功!");
        }
        return Result.success("修改成功");
    }

    @PostMapping("/login")
    @ApiOperation("登录接口")
    public Result login(@Valid @RequestBody LoginVO params) {
        return Result.data(loginService.login(params.getPhone(), params.getPassword(), 0));
    }

    @GetMapping("/logout")
    @ApiOperation("用户登出")
    public Result logout() {
        loginService.logout(securityMemberService.getMemberPhone());
        return Result.success();
    }
}
